/*
 * Flyweight pattern has structural purpose, applies to objects and uses sharing to support large numbers of fine-grained
 * objects efficiently. The pattern can be used to reduce memory usage when you need to create a large number of similar objects.
 * 
 * when one instance of a class can be used to provide many "virtual instances"
 * when all of the following are true
 * an application uses a large number of objects
 * storage costs are high because of the sheer quantity of objects
 * most object state can be made extrinsic
 * many groups of objects may be replaced by relativly few shared objects once extrinsic state is removed
 * the application doesn't depend on object identity
 */

#ifndef _CPP_DESIGN_PATTERN_FLYWEIGHT_H
#define _CPP_DESIGN_PATTERN_FLYWEIGHT_H

#include <iostream>
#include <map>

class Flyweight
{
public:
    virtual ~Flyweight() {}
    virtual void operation() = 0;
};

class UnsharedConcreteFlyweight : public Flyweight
{
public:
    UnsharedConcreteFlyweight(const int intrinsic_state) : state_(intrinsic_state) {}

    ~UnsharedConcreteFlyweight() {}

    void operation();

private:
    int state_;
};

class ConcreteFlyweight : public Flyweight
{
public:
    ConcreteFlyweight(const int all_state) : state_(all_state) {}

    ~ConcreteFlyweight() {}

    void operation();

private:
    int state_;
};

class FlyweightFactory
{
public:
    ~FlyweightFactory();

    Flyweight *getFlyweight(const int);

private:
    std::map<int, Flyweight *> flies_;
};

#endif